#ifndef ASTNODE_H
#define ASTNODE_H
#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
using namespace std;

class Program;
class Program_Body;
class Const_Declaration;
class Const_Variable;
class Type_Declaration;
class Var_Declaration;
class Type;
class Subprogram_Declaration;
class Formal_Parameter;
class Statement;
class Compound_Statement;
class Assign_Statement;
class Procedure_Statement;
class IF_Statement;
class CASE_Statement;
class WHILE_Statement;
class REPEAT_Statement;
class FOR_Statement;
class Variable;
class Branch;
class Expression;
class Simple_Expression;
class Term;
class Factor;
class Unsigned_Const_Variable;

typedef struct _node{
    string id;
    int line;
    void print(){
        cout << id << " " << line << endl;
    }
} Node;

class Program{
public:
    Node ID;
    vector<Node> para_list;
    Program_Body* program_body;
    void print();
};

class Program_Body{
public:
    vector<Const_Declaration*> const_declaration;
    vector<Type_Declaration*> type_declaration;
    vector<Var_Declaration*> var_declaration;
    vector<Subprogram_Declaration*> subprogram_declaration;
    Compound_Statement* compound_statement;
    void print();
};

class Const_Declaration{
public:
    Node ID;
    Const_Variable* const_variable;
    void print();
};

class Const_Variable{
public:
    string id;
    Node var_value;

    int int_value;
    double float_value;
    char c;
    string str;

    string mold; // id int float char string
    bool is_minus;
    void print();
};

class Type_Declaration{
public:
    Node ID;
    Type* type;
    void print();
};

class Var_Declaration{
public:
    vector<Node> ID;
    Type* type;
    void print();
};

class Type{
public:
    string mold; // standard array record
    Node standard;
    vector<pair<Const_Variable*, Const_Variable*>> array_range;
    vector<Var_Declaration*> var_declaration;
    string array_type; //standard record
    void record_print();
    void print();
};

class Subprogram_Declaration{
public:
    string mold; // function procedure
    Node ID;
    Node return_type;
    Program_Body* program_body;
    vector<Formal_Parameter*> parameter;
    void print();
};

class Formal_Parameter{
public:
    vector<Node> ID;
    Node type;
    bool is_reference;
    void print();
};

class Statement{
public:
    string type;//assign procedure compound if case while repeat for
    //string statementType;//区别于type，取值为"void"或"error"
	//int line;
	//bool is_return_statement;//是否是返回值语句
};

class Compound_Statement : public Statement{
public:
    vector<Statement*> statement_list;
    void print();
};

class Assign_Statement : public Statement{
public:
    Variable* variable;
    Expression* expression;
    void print();
};

class Procedure_Statement : public Statement{
public:
    Node ID;
    vector<Expression*> actual_parameter;
    void print();
};

class IF_Statement : public Statement{
public:
    Expression* expression;
    Statement* then_statement;
    Statement* else_statement;
    void print();
};

class CASE_Statement : public Statement{
public:
    Expression* expression;
    vector<Branch*> branch;
    void print();
};

class WHILE_Statement : public Statement{
public:
    Expression* expression;
    Statement* statement;
    void print();
};

class REPEAT_Statement : public Statement{
public:
    vector<Statement*> statement;
    Expression* expression;
    void print();
};

class FOR_Statement : public Statement{
public:
    Node ID;
    Expression* first_expression;
    Expression* second_expression;
    bool is_up;
    Statement* statement;
    void print();
};

class Variable{
public:
    Node ID;
    int type;// 3位 standard array record
    vector<string> record_ID;
    vector<vector<Expression*>> array_range;
    vector<int> order;//0 array 1 record
    void print();
};

class Branch{
public:
    vector<Const_Variable*>const_list;
    Statement* statement;
    void print();
};

class Expression{
public:
    string operationType;//relop single
    string relop_type;//EQUAL NEQUAL LESS LE GREATER GE
    Simple_Expression* operand_left;
    Simple_Expression* operand_right;
    void print();
};

class Simple_Expression{
public:
    string operationType;//ADD SUB ADDOP single
    string ADDOP_type;//ADD SUB OR
    Simple_Expression* operand_left;
    Term* operand_right;
    void print();
};

class Term{
public:
    string operationType;//MULOP single
    string MULOP_type;//MUL DIVISION DIV MOD AND
    Term* operand_left;
    Factor* operand_right;    
    void print();
};

class Factor{
public:
    int type;// 1 2 3 4 5 
    /*
    1 unsign_const_variable 
    2 variable
    3 ID LPAR expression_list RPAR 
    4 LPAR expression RPAR 
    5 NOT factor
    */
    Unsigned_Const_Variable* unsigned_const_variable;
    Variable* variable;
    Node ID;
    vector<Expression*> func_expression;
    Expression* expression;
    bool is_not;
    Factor* factor;
    void print();
};

class Unsigned_Const_Variable{
public:
    Node var_value;

    int int_value;
    double float_value;
    char c;
    string str;

    string mold; // int float char string
    void print();
};
#endif